import argparse
import os
import sys
import json
import subprocess
from openai import OpenAI
API_KEY = os.getenv("OPENROUTER_API_KEY","ollama")
BASE_URL = os.getenv("OPENROUTER_BASE_URL", default="https://openrouter.ai/api/v1")
def main():
p = argparse.ArgumentParser()
p.add_argument("-p", required=True)
args = p.parse_args()
model = os.getenv(
"LOCAL_MODEL",# 由于是学习的代码 这里先给系统添加环境变量 调用本地ollama
default="anthropic/claude-haiku-4.5"
)
if not API_KEY:
raise RuntimeError("OPENROUTER_API_KEY is not set")
client = OpenAI(api_key=API_KEY, base_url=BASE_URL)
messages = [{"role":"user","content":args.p}]
while True:# Loop
# 调用LLM
chat = client.chat.completions.create(
model=model,
messages=messages,
# 所有agent工具集
tools=[
# 给模型注册read这个工具(注册!=实现)
{
"type":"function",
"function":{
"name":"Read",
"description":"Read and return the contents of a file",
"parameters":{
"type":"object",
"properties":{
"file_path":{
"type":"string",
"description":"The path to the file to read"
}
},
"required":["file_path"]
}
}
},
# 给模型注册Write工具
{
"type":"function",
"function":{
"name":"Write",
"description":"Write content to a file",
"parameters":{
"type":"object",
"properties":{
"file_path":{
"type":"string",
"description":"The path of the file write to"
},
"content":{
"type":"string",
"description":"The content to write to the file"
}
},
"required":["file_path","content"]
}
}
},
# 给模型注册Bash工具
{
"type":"function",
"function":{
"name":"Bash",
"description":"Execute a shell command",
"parameters":{
"type":"object",
"properties":{
"command":{
"type":"string",
"description":"The command to execute"
}
},
"required":["command"]
}
}
}
]
)
if not chat.choices or len(chat.choices) == 0:
raise RuntimeError("no choices in response")
message = chat.choices[0].message
# 先把助手消息加入历史
messages.append(message.model_dump())
# 如果没有工具调用 说明任务完成了 可以输出内容了
if not getattr(message,"tool_calls",None):
print(message.content)
break
for tool_call in message.tool_calls:
tool_name = tool_call.function.name
tool_args = json.loads(tool_call.function.arguments)
if tool_name == "Read":
file_path = tool_args["file_path"]
with open(file_path,"r",encoding="utf-8") as f:
content = f.read()
# 将工具输出的文件内容返回给历史消息 供LLM参考
messages.append({
"role":"tool",
"tool_call_id":tool_call.id,
"content":content
})
elif tool_name == "Write":
file_path = tool_args["file_path"]
content = tool_args["content"]
# 写入文件 不存在就创建 存在就覆盖
with open(file_path,"w",encoding="utf-8") as f:
f.write(content)
messages.append({
"role":"tool",
"tool_call_id":tool_call.id,
"content":f"Wrote to {file_path}"
})
elif tool_name == "Bash":
command = tool_args["command"]
result = subprocess.run(
command,
shell=True,
capture_output=True,
text=True
)
output = result.stdout + result.stderr
messages.append({
"role":"tool",
"tool_call_id":tool_call.id,
"content":output
})
# You can use print statements as follows for debugging, they'll be visible when running tests.
print("Logs from your program will appear here!", file=sys.stderr)
# # print(chat.choices[0].message.content)
# message=chat.choices[0].message
# #这里让LLM真正使用工具Read
# if message.tool_calls:# 如果调用了read就返回文件内容
# tool_call = message.tool_calls[0]
# tool_name = tool_call.function.name
# tool_args = json.loads(
# tool_call.function.arguments
# )
# if tool_name == "Read":
# file_path = tool_args["file_path"]
# with open(file_path,"r",encoding="utf-8") as f:
# content = f.read()
# print(content)
# else: # 如果没有调用Read的打算就直接返回原内容
# print(message.content)
if __name__ == "__main__":
main()